package org.cainiao.basic.concurrent.lock.juc.reentrantlock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import static org.cainiao.util.Util.println;
import static org.cainiao.util.Util.silentSleep;

public class ReentrantLockTest {

    private static final Lock LOCK = new ReentrantLock();
    private static final Condition CONDITION_1 = LOCK.newCondition();
    private static final Condition CONDITION_2 = LOCK.newCondition();

    public static void main(String[] args) {
        new Thread(() -> {
            println("start");
            silentSleep(1000);

            println("lock");
            // 进入临界区
            LOCK.lock();
            println("in lock");

            println("CONDITION_2 signal start");
            CONDITION_2.signal();
            println("CONDITION_2 signal end");

            println("CONDITION_1 signal start");
            CONDITION_1.signal();
            println("CONDITION_1 signal end");

            println("unlock");
            LOCK.unlock();
            // 出临界区
        }, "Thread 1").start();

        new Thread(() -> {
            println("start");

            println("lock");
            LOCK.lock();
            // 进入临界区
            println("in lock");

            println("CONDITION_1 await");
            try {
                CONDITION_1.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            println("CONDITION_1 await after");

            silentSleep(3000);
            println("unlock");
            LOCK.unlock();
            // 出临界区
        }, "Thread 2").start();

        new Thread(() -> {
            println("start");
            silentSleep(500);

            println("lock");
            LOCK.lock();
            // 进入临界区
            println("in lock");

            println("CONDITION_2 await");
            try {
                CONDITION_2.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            println("CONDITION_2 await after");

            silentSleep(3000);
            println("unlock");
            LOCK.unlock();
            // 出临界区
        }, "Thread 3").start();
    }
}
